from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from apps.API.electricSigature.models import *
from datetime import datetime,timedelta
import hashlib
import json
import base64
# ==================== 核心功能实现 ====================
class Part11ComplianceSystem():
    def __init__(self):
        self.crypto_backend = default_backend()
    
    def _log_audit_event(self, event_type, user_id=None, description=None, ip_address=None):
        """内部方法：记录审计日志"""
        log = AuditLog(
            event_type=event_type,
            user_id=user_id,
            description=description,
            ip_address=ip_address
        )
        db.session.add(log)
    
    def add_user(self, user_id, name, role, password):
        """添加新用户到系统
        参数:
            user_id (str): 用户唯一ID
            name (str): 用户全名
            role (str): 用户角色
            password (str): 用户密码(明文)
        
        返回:
            User: 创建的用户对象
        
        异常:
            ValueError: 如果用户已存在
        """
        # 检查用户是否已存在
        if AuditUsers.query.get(user_id):
            raise ValueError(f"User {user_id} already exists")
        # 创建新用户
        new_user = AuditUsers(
            user_id=user_id,
            name=name,
            role=role,
            is_active=True
        )
        new_user.set_password(password)
        # 添加到数据库
        db.session.add(new_user)
        # 记录审计日志
        self._log_audit_event(
            event_type="USER_ADD",
            user_id=user_id,
            description=f"Added new user {user_id} with role {role}"
        )
        db.session.commit()
        return new_user
    def generate_key_pair(self, user_id, key_size=2048):
        """为用户生成RSA密钥对"""
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=key_size,
            backend=self.crypto_backend
        )
        # 序列化私钥(PEM格式)
        private_pem = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        ).decode('utf-8')
        # 获取公钥
        public_key = private_key.public_key()
        public_pem = public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        ).decode('utf-8')
        # 存储到数据库
        user = AuditUsers.query.filter(AuditUsers.user_id==user_id)
        if not user:
            raise ValueError("User not found")
        # 保存公钥到用户记录
        AuditUsers.query.filter(AuditUsers.user_id==user_id).update({"public_key":public_pem})
        # 创建私钥记录
        new_key = UserPrivateKey(
            user_id=user_id,
            private_key_pem=private_pem,
            expires_at=datetime.now() + timedelta(days=365)  # 1年后过期
        )
        db.session.add(new_key)
        db.session.commit()
        return private_pem, public_pem
    
    def sign_data(self, user_id, data, signing_purpose):
        """使用用户的私钥对数据进行签名"""
        # if not self.authenticate_user(user_id=user_id, password=password):
        #     raise ValueError("使用用户的私钥对数据进行签名:Authentication failed")
        # 获取用户最新私钥
        private_key_record = UserPrivateKey.query.filter_by(
            user_id=user_id,
            is_active=True
        ).order_by(
            UserPrivateKey.created_at.desc()
        ).first()
        if not private_key_record:
            raise ValueError("No active private key found for user")
        # 加载私钥
        private_key = serialization.load_pem_private_key(
            private_key_record.private_key_pem.encode(),
            password=None,
            backend=self.crypto_backend
        )
        # 创建签名载荷(包含数据和元数据)
        timestamp=datetime.now().replace(microsecond=0).isoformat()
        signature_payload = {
            "data": data,
            "signing_purpose": signing_purpose,
            "timestamp": timestamp,
            "user_id": user_id
        }
        payload_str = json.dumps(signature_payload, sort_keys=True)
        # 生成签名(RSA-PSS)
        # print("生成签名！！")
        # print(payload_str)
        signature = private_key.sign(
            payload_str.encode(),
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return {
            "signature": base64.b64encode(signature).decode('utf-8'),
            "payload": signature_payload,
            "algorithm": "RSA-PSS-SHA256",
            "timestamp":timestamp
        }
    
    def verify_signature(self, data, signature_package):
        """验证签名"""
        try:
            # 获取签名用户
            user_id = signature_package['payload']['user_id']
            user = AuditUsers.query.get(user_id)
            if not user or not user.public_key:
                return False, "User or public key not found"
            # 加载公钥
            public_key = serialization.load_pem_public_key(
                user.public_key.encode(),
                backend=self.crypto_backend
            )
            # 验证签名
            # print("验证签名！！")
            # print(signature_package['payload'])
            public_key.verify(
                base64.b64decode(signature_package['signature']),
                json.dumps(signature_package['payload'], sort_keys=True).encode(),
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            # 验证数据完整性
            if signature_package['payload']['data'] != data:
                return False, "Data mismatch"
            return True, "Signature is valid"
        except Exception as e:
            print(str(e))
            return False, f"Verification failed: {str(e)}"
    
    def create_signed_record(self, record_id, record_type, content, created_by, password,passd_check=True):
        """创建并签名电子记录"""
        # 1. 认证用户
        if passd_check == True:
            if not self.authenticate_user(user_id=created_by, password=password):
                raise ValueError("创建并签名电子记录:Authentication failed")
        # 2. 计算内容哈希
        content_hash = hashlib.sha256(content.encode()).hexdigest()
        # 3. 创建记录
        new_record = ElectronicRecord(
            record_id=record_id,
            record_type=record_type,
            content=content,
            content_hash=content_hash,
            created_by=created_by
        )
        db.session.add(new_record)
        # 4. 记录审计日志
        self._log_audit_event(
            event_type="RECORD_CREATE",
            user_id=created_by,
            description=f"Created record {record_id} of type {record_type}"
        )
        # 5. 自动创建初始签名
        signature_package = self.sign_data(
            user_id=created_by,
            data={
                "record_id": record_id,
                "content_hash": content_hash,
            },
            signing_purpose="Creation"
        )
        # 6. 存储签名
        new_signature = ElectronicSignature(
            record_id=record_id,
            user_id=created_by,
            signature_data=signature_package['signature'],
            signing_purpose=signature_package['payload']['signing_purpose'],
            signature_algorithm=signature_package['algorithm'],
            timestamp=signature_package['timestamp'],
            certificate_info=json.dumps({
                "public_key": AuditUsers.query.get(created_by).public_key
            })
        )
        db.session.add(new_signature)
        db.session.commit()
        return new_record
    
    def authenticate_user(self, user_id, password):
        """用户认证"""
        user = AuditUsers.query.filter_by(user_id=user_id, is_active=True).first()
        if not user:
            return False
        return user.check_password(password)
    
    def add_record_signature(self, record_id,  user_id, signing_purpose, password):
        """为记录添加新签名"""
        # 1. 获取记录
        record = ElectronicRecord.query.get(record_id)
        if not record:
            raise ValueError("Record not found")
        # 2. 认证用户
        if not self.authenticate_user(user_id, password):
            raise ValueError("为记录添加新签名:Authentication failed")
        # 3. 创建签名
        signature_package = self.sign_data(
            user_id=user_id,
            data={
                "record_id": record_id,
                "content_hash": record.content_hash,
            },
            signing_purpose=signing_purpose,
        )
        # 4. 存储签名
        new_signature = ElectronicSignature(
            record_id=record_id,
            user_id=user_id,
            signature_data=signature_package['signature'],
            signing_purpose=signature_package['payload']['signing_purpose'],
            signature_algorithm=signature_package['algorithm'],
            timestamp=signature_package["timestamp"],
            certificate_info=json.dumps({
                "public_key": AuditUsers.query.get(user_id).public_key
            })
        )
        db.session.add(new_signature)
        # 5. 记录审计日志
        self._log_audit_event(
            event_type="RECORD_SIGN",
            user_id=user_id,
            description=f"Added signature to record {record_id} for purpose {signing_purpose}"
        )
        db.session.commit()
        return new_signature
    
    def verify_record_signatures(self, record_id):
        """验证记录的所有签名"""
        record = ElectronicRecord.query.get(record_id)
        if not record:
            return False, "Record not found"
        signatures = ElectronicSignature.query.filter_by(
            record_id=record_id
        ).all()
        if not signatures:
            return False, "No signatures found for record"
        verification_results = []
        all_valid = True
        for sig in signatures:
            # 重建签名时的数据
            signed_data = {
                "content_hash": record.content_hash,
                "record_id": record_id
            }
            # 重建签名包
            signature_package = {
                "signature": sig.signature_data,
                "payload": {
                    "data": signed_data,
                    "signing_purpose": sig.signing_purpose,
                    "timestamp": sig.timestamp.isoformat(),
                    "user_id": sig.user_id
                },
                "algorithm": sig.signature_algorithm
            }
            # 验证签名
            is_valid, message = self.verify_signature(signed_data, signature_package)
            verification_results.append({
                "signature_id": sig.signature_id,
                "user_id": sig.user_id,
                "timestamp": sig.timestamp.isoformat(),
                "purpose": sig.signing_purpose,
                "is_valid": is_valid,
                "message": message
            })
            if not is_valid:
                all_valid = False
        return all_valid, verification_results
    # ... (保留之前的用户管理、审计日志等方法)

### 实例化 ###
system=Part11ComplianceSystem()
